/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Sylvain Sicard - initial API and implementation
 ******************************************************************************/
/*
 * Created on 24 oct. 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package fr.jade.console.cmd;

import java.rmi.RemoteException;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.Interface;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.fractal.api.control.ContentController;
import org.objectweb.fractal.api.control.NameController;
import org.objectweb.fractal.api.control.SuperController;
import org.objectweb.fractal.util.Fractal;

import fr.jade.console.core.AbstractCommand;
import fr.jade.console.core.Command;
import fr.jade.console.core.Environment;
import fr.jade.fraclite.api.control.GenericAttributeController;
import fr.jade.fraclite.api.control.NoSuchAttributeException;
import fr.jade.fraclite.util.FracLite;
import fr.jade.util.FractalNavigator;
import fr.jade.util.FractalUtil;

/**
 * @author Sylvain Sicard
 */
public class Ls extends AbstractCommand implements Command{

  public String getDescription(){
    return "introspects component";
  }
  
  public String getHelp(){
    return "ls <option>\n"+
            "Options :\n"+
            "\t-a list attributes of curent component\n"+
            "\t-i list interfaces of curent component\n"+
            "\t-c list subcomponent of curent component\n"+
            "\t-C list recursively subcomponent of curent component\n"+
            "\t-bo list \"out\" bindings of curent component\n"+
            "\t-bi list \"in\" bindings of curent component\n"+
            "\t-s list super component of curent component\n"+
            "\t-S list recursively super component of curent component\n";
  }
  
  public String getName() {
    return "ls";
  }
  
	/**
	 * @param args args[0] : Ls
	 *             args[1] : option
	 */ 
	public Object execute(String[] args, Environment env) throws Throwable {
		String opt;
		
		if(args.length == 1){
			opt = "-c";
		}else{
			opt = args[1];
		}
		
		Component current = getCurrent(env);
		System.out.println(Fractal.getNameController(current).getFcName());
		
		if(opt.equals("-i")){
			printItfs(current);
		}else if (opt.equals("-C")){
			printSubCmp(current, "", true);
		}else if (opt.equals("-c")){
      printSubCmp(current, "", false);
    }else if (opt.equals("-bo")){
			printOutBindings(current);
		}else if (opt.equals("-bi")){
      printInBindings(current);
    }else if (opt.equals("-S")){
			printSuperCmp(current, "", true);
		}else if (opt.equals("-s")){
      printSuperCmp(current, "", false);
    }else if(opt.equals("-a")){
		  printAttributes(current);
		}else if (opt.equals("-help")){
			System.out.println(getHelp());
		}else{
			System.out.println("Ls : " + opt + " unknown option");
		}
		return null;
	}
	
	
	private void printAttributes(Component curent) {
    
	  try {
      GenericAttributeController gac = FracLite.getAttributeController(curent);
      for(String key : gac.listFcAtt()){
        try {
          System.out.println(key + " : "+ gac.getAttribute(key));
        } catch (NoSuchAttributeException e) {
          System.out.println(key + " : WARNING cannot read attribute");
        }
      }
    } catch (NoSuchInterfaceException e) {
      System.out.println("Component is not parametric");
    }
	  
  }

	private void printSuperCmp(Component c, String separ, boolean recursive) throws Exception {
    try{
      SuperController cc = FractalUtil.getOptSuperController(c);
        
      for (Component comp : cc.getFcSuperComponents()) {
        try{
          String name = FractalNavigator.getName(comp);
          System.out.println(separ + "|--" + name);
          if(recursive) printSubCmp(comp, "|  " + separ, recursive);
        }catch(RemoteException e){
          e.printStackTrace();
        }
      }
    }catch(NoSuchInterfaceException e){
      // ignored
    }
  }

	private void printItfs(Component cmp) throws Exception{
		for(Object itf : cmp.getFcInterfaces()){
			System.out.println("|--"+((Interface)itf).getFcItfName());
		}
	}
	
	private void printSubCmp(Component c, String separ, boolean recursive) throws Exception {
	  try{
	    ContentController cc = FractalUtil.getOptContentController(c);
				
			for (Component comp : cc.getFcSubComponents()) {
			  try{
  				String name = FractalNavigator.getName(comp);
  				System.out.println(separ + "|--" + name);
  				if(recursive) printSubCmp(comp, "|  " + separ, recursive);
			  }catch(RemoteException e){
		      e.printStackTrace();
		    }
			}
	  }catch(NoSuchInterfaceException e){
	    // ignored
	  }
	}
	
	private void printOutBindings(Component c) throws Exception{
	  
	  	BindingController bc = null;
	  	String servname = null;
	  	bc = Fractal.getBindingController(c);
  	    String [] l = bc.listFc();
  	    if (l!=null){
  	      // we have some client itf
  	     
  	      for (int i = 0; i<l.length; i++){
  	     	  Interface serv = (Interface)(bc.lookupFc (l[i]));
  	     	  if(serv!=null){
  	     	  	Component cserv = serv.getFcItfOwner();
  	     	  	if (cserv != null){ 
  	     	  		servname = ((NameController)(cserv.getFcInterface("name-controller"))).getFcName();
  	     	  		System.out.println("|--"+l[i]+" ----> "+servname+"."+serv.getFcItfName()); 	  	     
  	     	  	}
  	     	  }else{
  	     	  	System.out.println("|--"+l[i]+" not bound");
  	     	  }
  	       }// end for
  	    }
	}
	
	
	private void printInBindings(Component c) throws Exception{
		  
		  	BindingController bc = null;
		  	String servname = null;
		  	bc = Fractal.getBindingController(c);
	  	    String [] l = bc.listFc();
	  	    if (l!=null){
	  	      // we have some client itf
	  	     
	  	      for (int i = 0; i<l.length; i++){
	  	     	  Interface serv = (Interface)(bc.lookupFc (l[i]));
	  	     	  if(serv!=null){
	  	     	  	Component cserv = serv.getFcItfOwner();
	  	     	  	if (cserv != null){ 
	  	     	  		servname = ((NameController)(cserv.getFcInterface("name-controller"))).getFcName();
	  	     	  		System.out.println("|--"+l[i]+" ----> "+servname+"/"+serv.getFcItfName()); 	  	     
	  	     	  	}
	  	     	  }else{
	  	     	  	System.out.println("|--"+l[i]+" not bound");
	  	     	  }
	  	       }// end for
	  	    }
		}
}
